/*
 * PhotonRTOS础光实时操作系统 -- Can驱动
 *
 * Copyright (C) 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Jiayuan Liang <liangjiayuan@kernelsoft.com>
 * Jun Huang <huangjun@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */
#include <asm/can.h>

McmcanType                  g_mcmcan;

IFX_INTERRUPT(canIsrTxHandler, 0, ISR_PRIORITY_CAN_TX);
void canIsrTxHandler(void)
{
    /* Clear the "Transmission Completed" interrupt flag */
    IfxCan_Node_clearInterruptFlag(g_mcmcan.canSrcNode.node, IfxCan_Interrupt_transmissionCompleted);
    /* Just to indicate that the CAN message has been transmitted by turning on LED0 */
    blinkLED();
}

IFX_INTERRUPT(canIsrRxHandler, 0, ISR_PRIORITY_CAN_RX);
void canIsrRxHandler(void)
{
    /* Clear the "Message stored to Dedicated RX Buffer" interrupt flag */
    IfxCan_Node_clearInterruptFlag(g_mcmcan.canDstNode.node, IfxCan_Interrupt_messageStoredToDedicatedRxBuffer);
    /* Clear the "New Data" flag; as long as the "New Data" flag is set, the respective Rx buffer is
     * locked against updates from received matching frames.
     */
    IfxCan_Node_clearRxBufferNewDataFlag(g_mcmcan.canDstNode.node, g_mcmcan.canFilter.rxBufferOffset);
    /* Read the received CAN message */
    IfxCan_Can_readMessage(&g_mcmcan.canDstNode, &g_mcmcan.rxMsg, g_mcmcan.rxData);

    /* Check if the received data matches with the transmitted one */
    if( ( g_mcmcan.rxData[0] == g_mcmcan.txData[0] ) &&
        ( g_mcmcan.rxData[1] == g_mcmcan.txData[1] ) &&
        ( g_mcmcan.rxMsg.messageId == g_mcmcan.txMsg.messageId ) )
    {
        /* Turn on the LED1 to indicate correctness of the received message */
    	blinkLED2();
    }
}

void arch_init_can(void)
{
    //initMcmcan

    /*******CAN module configuration and initialization*******/
    //load default CAN module configuration into configuration structure
    IfxCan_Can_initModuleConfig(&g_mcmcan.canConfig, &MODULE_CAN0);
    //initialize CAN module with the default configuration
    IfxCan_Can_initModule(&g_mcmcan.canModule, &g_mcmcan.canConfig);

    /*******Source CAN node configuration and initialization*******/
    IfxCan_Can_initNodeConfig(&g_mcmcan.canNodeConfig, &g_mcmcan.canModule);
    //g_mcmcan.canNodeConfig.busLoopbackEnabled = TRUE;
    g_mcmcan.canNodeConfig.busLoopbackEnabled = FALSE;


    IFX_CONST IfxCan_Can_Pins Can_Pin = {
    		    .txPin = (IfxCan_Txd_Out *)&IfxCan_TXD00_P20_8_OUT,           /**< \brief Specifies the transmit pin */
    		    .txPinMode = IfxPort_OutputMode_pushPull,       /**< \brief Specifies the transmit pin output mode IfxPort_OutputMode_pushPull */
    		    .rxPin = (IfxPort_InputMode *)&IfxCan_RXD00B_P20_7_IN,           /**< \brief Specifies the receive pin */
    		    .rxPinMode = IfxPort_InputMode_noPullDevice,       /**< \brief Specifies the receive pin as input mode IfxPort_InputMode_noPullDevice */
    		    .padDriver = IfxPort_PadDriver_cmosAutomotiveSpeed2,       /**< \brief Pad driver IfxPort_PadDriver_cmosAutomotiveSpeed2 */
    };
    g_mcmcan.canNodeConfig.pins = &Can_Pin;
    g_mcmcan.canNodeConfig.nodeId = IfxCan_NodeId_0;
    g_mcmcan.canNodeConfig.frame.type = IfxCan_FrameType_transmit;
    //g_mcmcan.canNodeConfig.frame.type = IfxCan_FrameType_transmitAndReceive;

    g_mcmcan.canNodeConfig.interruptConfig.transmissionCompletedEnabled = TRUE;
    //g_mcmcan.canNodeConfig.interruptConfig.transmissionCompletedEnabled = FALSE;

    //g_mcmcan.canNodeConfig.interruptConfig.traco.priority = ISR_PRIORITY_CAN_TX;
    g_mcmcan.canNodeConfig.interruptConfig.traco.interruptLine = IfxCan_InterruptLine_0;
    g_mcmcan.canNodeConfig.interruptConfig.traco.typeOfService = IfxSrc_Tos_cpu0;
    IfxCan_Can_initNode(&g_mcmcan.canSrcNode, &g_mcmcan.canNodeConfig);

    //Initialization of the TX message with the default configuration
    IfxCan_Can_initMessage(&g_mcmcan.txMsg);
}

void arch_send_can_message(unsigned short id, uint8 *buf, uint8 len)
{
	memcpy(g_mcmcan.txData, buf, len);
	g_mcmcan.txMsg.messageId = id;
	g_mcmcan.txMsg.dataLengthCode = len;

	while( IfxCan_Status_notSentBusy ==
		   IfxCan_Can_sendMessage(&g_mcmcan.canSrcNode, &g_mcmcan.txMsg, &g_mcmcan.txData[0]) )
	{
	}
}

